<!doctype html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <style>
        body {
            padding: 0;
            margin: 0;
            overflow: hidden;
        }

        #cas {
            display: block;
            margin: auto;
        }
    </style>
    <title>操控文字图片的数据</title>
</head>
<body>
<div>
    <canvas id='cas' width="1200" height="800" style="background-color:#262929">浏览器不支持canvas</canvas>
</div>
<div style="display:none">
    <div class="ele">WELCOM</div>
    <div class="ele">图片粒子化</div>
    <div class="ele" data-dr="2"><img src="love2.png" alt=""/></div>
    <div class="ele">文字粒子化</div>
    <div class="ele">WAxes</div>
</div>

<script>
    (function(){
        var dr;
        var canvas = document.getElementById("cas"),
            ele = document.querySelectorAll(".ele"),
            context = canvas.getContext('2d');

        var focallength = 250,index = 0;
        var img = new Image();
        var pause = false;
        var dots = [];

        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;

        var RAF = (function() {
            return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
                        return window.setTimeout(callback, 1000 / 60);
                    };
        })();

        var Dot = function (centerX, centerY, centerZ, radius, color) {
            this.dx = centerX;
            this.dy = centerY;
            this.dz = centerZ;
            this.tx = 0;
            this.ty = 0;
            this.tz = 0;
            this.z = centerZ;
            this.x = centerX;
            this.y = centerY;
            this.radius = radius;
            this.color = color;
        };

        Dot.prototype = {
            paint: function () {
                context.save();
                var scale = (this.z + focallength) / (2 * focallength);
                context.fillStyle = "rgba(" + this.color.a + "," + this.color.b + "," + this.color.c + "," + scale + ")";
                context.fillRect(canvas.width / 2 + (this.x - canvas.width / 2) * scale, canvas.height / 2 + (this.y - canvas.height / 2) * scale, this.radius * scale*2 , this.radius * scale*2)
                context.restore();
            }
        };

        Array.prototype.forEach = function (callback) {
            for (var i = 0; i < this.length; i++) {
                callback.call(this[i]);
            }
        }

        eachEle();

        function eachEle() {
            dr = 3;
            if (ele[index].getAttribute('data-dr') !== null) {
                dr = parseInt(ele[index].getAttribute('data-dr'))
            }
            context.clearRect(0, 0, canvas.width, canvas.height);
            if (ele[index].innerHTML.indexOf("img") >= 0) {
                img.src = ele[index].getElementsByTagName("img")[0].src;
                imgload(img, function () {
                    context.drawImage(img, canvas.width / 2 - img.width / 2, canvas.height / 2 - img.height / 2);
                    dots = getimgData();
                    initAnimate();
                })
            }
            else {
                var text = ele[index].innerHTML;
                for (var i = 0; i < text.length; i++) {
                    context.save();
                    var fontSize = Math.random() * 100 + 100;
                    context.font = fontSize + "px bold";
                    context.textAlign = "center";
                    context.textBaseline = "middle";
                    var code = text.charAt(i);
                    context.fillStyle = "rgba(" + parseInt(Math.random() * 125 + 130) + "," + parseInt(Math.random() * 125 + 130) + "," + parseInt(Math.random() * 125 + 130) + " , 1)";
                    context.fillText(code, canvas.width / 2 - ((text.length / 2 - i) * 150), canvas.height / 2);
                    context.restore();
                }
                dots = getimgData();
                initAnimate();
            }
            index < (ele.length - 1) ? index++ : index = 0;
        }

        function imgload(img, callback) {
            if (img.complete) {
                callback.call(img);
            }
            else {
                img.onload = function () {
                    callback.call(this);
                }
            }
        }

        var lastTime;

        function initAnimate() {
            dots.forEach(function () {
                this.x = getRandom(0, canvas.width);
                this.y = getRandom(0, canvas.height);
                this.z = getRandom(-focallength, focallength);

                this.tx = getRandom(0, canvas.width);
                this.ty = getRandom(0, canvas.height);
                this.tz = getRandom(-focallength, focallength);
            });
            dots.sort(function (a, b) {
                return b.z - a.z;
            });
            dots.forEach(function () {
                this.paint();
            });
            lastTime = new Date();
            animate();
        }

        var derection = true;

        function animate() {
            animateRunning = true;
            var thisTime = +new Date();
            context.save();
            context.globalCompositeOperation = 'destination-out';
            context.globalAlpha = 0.1;
            context.fillRect(0, 0, canvas.width, canvas.height);
            context.restore();

            var sulv = 0.1;
            dots.forEach(function () {
                var dot = this;
                if (derection) {
                    if (Math.abs(dot.dx - dot.x) < 0.1 && Math.abs(dot.dy - dot.y) < 0.1 && Math.abs(dot.dz - dot.z) < 0.1) {
                        dot.x = dot.dx;
                        dot.y = dot.dy;
                        dot.z = dot.dz;
                        if (thisTime - lastTime > 300) derection = false;
                    } else {
                        dot.x = dot.x + (dot.dx - dot.x) * sulv;
                        dot.y = dot.y + (dot.dy - dot.y) * sulv;
                        dot.z = dot.z + (dot.dz - dot.z) * sulv;
                        lastTime = +new Date()
                    }
                }
                else {
                    if (Math.abs(dot.tx - dot.x) < 0.1 && Math.abs(dot.ty - dot.y) < 0.1 && Math.abs(dot.tz - dot.z) < 0.1) {
                        dot.x = dot.tx;
                        dot.y = dot.ty;
                        dot.z = dot.tz;
                        pause = true;
                    } else {
                        dot.x = dot.x + (dot.tx - dot.x) * sulv;
                        dot.y = dot.y + (dot.ty - dot.y) * sulv;
                        dot.z = dot.z + (dot.tz - dot.z) * sulv;
                        pause = false;
                    }
                }
            });
            dots.sort(function (a, b) {
                return b.z - a.z;
            });
            dots.forEach(function () {
                this.paint();
            });

            if (!pause){
                RAF(animate)
            }else {
                context.clearRect(0, 0, canvas.width, canvas.height);
                eachEle();
                derection = true;
                pause = false;
            }
        }

        function getRandom(a, b) {
            return Math.random() * (b - a) + a
        }

        function getimgData() {
            var imgData = context.getImageData(0, 0, canvas.width, canvas.height);
            context.clearRect(0, 0, canvas.width, canvas.height);
            var dots = [];
            var canbreak = false;
            for (var x = 0; x < imgData.width; x += dr) {
                for (var y = 0; y < imgData.height; y += dr) {
                    var i = (y * imgData.width + x) * 4;
                    if (imgData.data[i + 3] > 128) {
                        var dot = new Dot(x - dr, y - dr, 0, dr, {
                            a: imgData.data[i],
                            b: imgData.data[i + 1],
                            c: imgData.data[i + 2]
                        });
                        dots.push(dot);
                    }
                }
            }
            console.log(dots.length)
            return dots;
        }
    }())
</script>

</body>
</html>